///<reference path="../../../../node_modules/rxjs/add/operator/catch.d.ts"/>
/**
 * Created by eku_mac on 9/5/17.
 */
/**
 * Http Intercepter Service
 * TODO: Add Loader and Toasty Service currently using console log
 * for showing errors and response and request completion;
 */
import { Injectable } from '@angular/core';
import {
         Http, ConnectionBackend, 
         RequestOptions, RequestOptionsArgs, 
         Response, Headers, Request 
       } from '@angular/http';
import {Observable}    from 'rxjs/Rx';
import { Subject }     from 'rxjs/Subject';
import { environment } from '../../../environments/environment';
// import { Observable } from 'rxjs/Observable';


@Injectable()
export class HttpService extends Http {
  public loading = new Subject<{loading: boolean, hasError: boolean, hasMsg: string}>();

  constructor(
    backend: ConnectionBackend,
    defaultOptions: RequestOptions,
  ) {
    super(backend, defaultOptions);
  }

  /**
   * Performs any type of http request.
   * @param url
   * @param options
   * @returns {Observable<Response>}
   */
  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    return super.request(url, options);
  }

  /**
   * Performs a request with `get` http method.
   * @param url
   * @param options
   * @returns {Observable<>}
   */
  get(url: string, options?: RequestOptionsArgs): Observable<any> {
    console.log('request options ---', options);
    this.requestInterceptor();
    return super.get(this.getFullUrl(url), this.requestOptions(options))
      .catch(this.onCatch.bind(this))
      .do((res: Response) => {
        this.onSubscribeSuccess(res);
      }, (error: any) => {
        this.onSubscribeError(error);
      })
      .finally(() => {
        this.onFinally();
      });
  }

  getLocal(url: string, options?: RequestOptionsArgs): Observable<any> {
    return super.get(url, options);
  }

  /**
   * Performs a request with `post` http method.
   * @param url
   * @param body
   * @param options
   * @returns {Observable<>}
   */
  // post(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
  //   this.requestInterceptor();
  //   return super.post(this.getFullUrl(url), body, this.requestOptions(options))
  //     .catch(this.onCatch.bind(this))
  //     .do((res: Response) => {
  //         this.onSubscribeSuccess(res);
  //         console.log('post success !', res);
  //     }, (error: any) => {
  //       this.onSubscribeError(error);
  //       console.log('post error !');
  //     })
  //     .finally(() => {
  //       this.onFinally();
  //       console.log('finally !');
  //     });
  // }

post(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
  console.log('request url in post method : ---', url);
    console.log('request options in post method ---', options);
    this.requestInterceptor();
    return super.post(this.getFullUrl(url), body, this.requestOptions(options))
      .map((res: Response) => {
          this.onSubscribeSuccess(res);
          console.log('http post res ---', res);
          return res.json();
      })
      .catch( error => {
        this.onSubscribeError(error);
        console.log('post error !');
        return  Observable.throw(new Error(error));
        // return Observable.throw(error.json().error || 'server error');
      });
  }

  // post(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
  //   this.requestInterceptor();
  //   return super.post(this.getFullUrl(url), body, this.requestOptions(options))
  //      .catch(this.onCatch.bind(this))
  //      .do((res: Response) => {
  //        console.log('s ---', res.status);
  //      },
  //      errors => {
  //        console.log('e ---', errors);
  //      }
  //      )
  // }

//     post(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
//     this.requestInterceptor();
//     return super.post(this.getFullUrl(url), body, this.requestOptions(options))
//     .map((res: Response)=>{
//        console.log( "post map", res);
//     })
//     .catch((error: any) => {
//       console.log( "post map error", error);
//       if (error.status === 500) {
//           return Observable.throw(new Error(error.status));
//       }
//       else if (error.status === 400) {
//           return Observable.throw(new Error(error.status));
//       }
//       else if (error.status === 409) {
//           return Observable.throw(new Error(error.status));
//       }
//       else if (error.status === 406) {
//           return Observable.throw(new Error(error.status));
//       }
//    })  ;
// }


  /**
   * Performs a request with `put` http method.
   * @param url
   * @param body
   * @param options
   * @returns {Observable<>}
   */
  put(url: string, body: any, options?: RequestOptionsArgs): Observable<any> {
    this.requestInterceptor();
    return super.put(this.getFullUrl(url), body, this.requestOptions(options))
      .catch(this.onCatch.bind(this))
      .do((res: Response) => {
        this.onSubscribeSuccess(res);
      }, (error: any) => {
        this.onSubscribeError(error);
      })
      .finally(() => {
        this.onFinally();
      });
  }

  /**
   * Performs a request with `delete` http method.
   * @param url
   * @param options
   * @returns {Observable<>}
   */
  delete(url: string, options?: RequestOptionsArgs): Observable<any> {
    this.requestInterceptor();
    return super.delete(this.getFullUrl(url), this.requestOptions(options))
      .catch(this.onCatch.bind(this))
      .do((res: Response) => {
        this.onSubscribeSuccess(res);
      }, (error: any) => {
        this.onSubscribeError(error);
      })
      .finally(() => {
        this.onFinally();
      });
  }


  /**
   * Request options.
   * @param options
   * @returns {RequestOptionsArgs}
   */
  private requestOptions(options?: RequestOptionsArgs): RequestOptionsArgs {
    if (options == null) {
      options = new RequestOptions();
      console.log('request options in request options function  : --- ')
    }

    // authorization  'Authorization': user && user.token,

    if (options.headers == null) {
      console.log('get local storage token ---', localStorage.getItem('username'));
      const user = localStorage.getItem('username') != "undefined" ? JSON.parse(localStorage.getItem('username')) : null;
      console.log('get localstorage token: ---', user);
      options.headers = new Headers({
        'Content-Type': 'application/json; charset=utf-8',
        'X-Easy-Token': user && user.token,
      });
    }
    console.log('options headers in request opitons function: ---', options.headers);
    return options;
  }

  /**
   * Build API url.
   * @param url
   * @returns {string}
   */
  private getFullUrl(url: string): string {

    return environment.API_ENDPOINT + url;
  }

  /**
   * Request interceptor.
   */
  private requestInterceptor(): void {
    console.log('Sending Request');
    // this.loaderService.showPreloader();
    this.loading.next({
      loading: true, hasError: false, hasMsg: ''
    });
  }

  /**
   * Response interceptor.
   */
  private responseInterceptor(): void {
    console.log('Request Complete');
    // this.loaderService.hidePreloader();
  }

  /**
   * Error handler.
   * @param error
   * @param caught
   * @returns {ErrorObservable}
   */
  private onCatch(error: any, caught: Observable<any>): Observable<any> {
    console.log('Something went terrible wrong and error is', error);
    // this.loaderService.popError();
    return Observable.of(error);
  }

  /**
   * onSubscribeSuccess
   * @param res
   */
  private onSubscribeSuccess(res: Response): void {
    this.loading.next({
      loading: false, hasError: false, hasMsg: ''
    });
  }

  /**
   * onSubscribeError
   * @param error
   */
  private onSubscribeError(error: any): void {
    console.log('Something Went wrong while subscribing', error);
    // this.loaderService.popError();
    this.loading.next({
      loading: false, hasError: true, hasMsg: 'Something went wrong'
    });
  }

  /**
   * onFinally
   */
  private onFinally(): void {
    this.responseInterceptor();
  }
}
